#![crate_type = "proc-macro"]
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, Data, DeriveInput, Fields};

#[proc_macro_attribute]
pub fn serde_for_json(_args: TokenStream, input: TokenStream) -> TokenStream {
    // 将输入解析为 DeriveInput 类型，这是所有 Rust 结构体和枚举的通用 AST
    let input = parse_macro_input!(input as DeriveInput);

    // 检查这是否是一个结构体，并拿到它的名称、字段列表等信息
    let struct_name = input.ident;
    let fields = match input.data {
        Data::Struct(data_struct) => data_struct.fields,
        _ => panic!("'serde_json' can only be used with structs!"),
    };

    // 生成代码，将结构体转换为 JSON 字符串
    let output = match fields {
        Fields::Named(fields_named) => {
            let field_names = fields_named.named.iter().map(|f| &f.ident);
            quote! {
                impl #struct_name {
                    pub fn to_json(&self) -> String {
                        serde_json::to_string(&json!({
                            #(stringify!(#field_names): self.#field_names,)*
                        })).unwrap()
                    }
                }
            }
        }
        Fields::Unnamed(fields_unnamed) => {
            let field_indices = 0..fields_unnamed.unnamed.len();
            quote! {
                impl #struct_name {
                    pub fn to_json(&self) -> String {
                        serde_json::to_string(&json!([
                            #(self.#field_indices,)*
                        ])).unwrap()
                    }
                }
            }
        }
        Fields::Unit => {
            quote! {
                impl #struct_name {
                    pub fn to_json(&self) -> String {
                        serde_json::to_string(&json!({})).unwrap()
                    }
                }
            }
        }
    };

    // 将生成的代码作为 TokenStream 返回
    output.into()
}

//
// #[proc_macro_attribute]
// pub fn run(_args: TokenStream, input: TokenStream) -> TokenStream {
//     // 将输入解析为函数节点
//     let input = parse_macro_input!(input as ItemFn);
//
//     // 获取函数名称、参数列表等信息
//     let func_name = &input.vis;
//     let func_args = &input.sig.inputs;
//
//     // 生成代码，在函数开始和结束时分别打印时间戳
//     let output = quote! {
//         #input
//
//         fn #func_name(#func_args) -> () {
//             println!("{} started", stringify!(#func_name));
//             let start = std::time::Instant::now();
//             let result = #func_name(#func_args);
//             let end = start.elapsed();
//             println!("{} finished in {}ms", stringify!(#func_name), end.as_millis());
//             result
//         }
//     };
//
//     // 将生成的代码作为 TokenStream 返回
//     output.into()
// }
